1 package edu.jiangxin.apktoolbox.file.password.recovery.category.bruteforce;
2
3 import edu.jiangxin.apktoolbox.file.password.recovery.RecoveryPanel;
4 import edu.jiangxin.apktoolbox.file.password.recovery.State;
5 import edu.jiangxin.apktoolbox.file.password.recovery.category.ICategory;
6 import edu.jiangxin.apktoolbox.file.password.recovery.checker.FileChecker;
7 import edu.jiangxin.apktoolbox.file.password.recovery.checker.IChecker;
8 import org.apache.commons.lang3.StringUtils;
9 import org.apache.logging.log4j.LogManager;
10 import org.apache.logging.log4j.Logger;
11
12 import javax.swing.*;
13 import java.util.concurrent.ExecutorService;
14 import java.util.concurrent.Executors;
15 import java.util.concurrent.TimeUnit;
16
17 public class BruteForceProxy implements ICategory {
18 private static final Logger logger = LogManager.getLogger(BruteForceProxy.class.getSimpleName());
19
20 private ExecutorService executorService;
21
22 private BruteForceFuture bruteForceFuture;
23
24 private static class BruteForceProxyHolder {
25 private static final BruteForceProxy instance = new BruteForceProxy();
26 }
27
28 private BruteForceProxy() {
29 }
30
31 public static BruteForceProxy getInstance() {
32 return BruteForceProxyHolder.instance;
33 }
34
35 private String startAndGet(int numThreads, int passwordLength, IChecker checker, String charsSet, RecoveryPanel panel) {
36 executorService = Executors.newFixedThreadPool(numThreads);
37 bruteForceFuture = new BruteForceFuture(numThreads);
38 BruteForceTaskParam param = new BruteForceTaskParam(numThreads, passwordLength, checker, charsSet);
39 for (int taskId = 0; taskId < numThreads; taskId++) {
40 BruteForceRunnable task = new BruteForceRunnable(taskId, param, bruteForceFuture, panel);
41 executorService.execute(task);
42 }
43 String password = null;
44 try {
45 password = bruteForceFuture.get();
46 } catch (Exception e) {
47 logger.info("Exception test: ", e);
48 } finally {
49 if (executorService.isShutdown()) {
50 executorService.shutdown();
51 }
52 }
53 return password;
54 }
55
56 @Override
57 public void start(RecoveryPanel panel) {
58 String charset = panel.getCharset();
59 logger.info("Charset: {}", charset);
60 if (StringUtils.isEmpty(charset)) {
61 JOptionPane.showMessageDialog(panel, "Character set is empty!");
62 return;
63 }
64
65 int minLength = panel.getMinLength();
66 int maxLength = panel.getMaxLength();
67 if (minLength > maxLength) {
68 JOptionPane.showMessageDialog(panel, "Minimum length is bigger than maximum length!");
69 return;
70 }
71 String password = null;
72 int totalNumber = 0;
73 for (int length = minLength; length <= maxLength; length++) {
74 totalNumber += (int)Math.pow(charset.length(), length);
75 }
76 panel.resetProgressMaxValue(totalNumber);
77 for (int length = minLength; length <= maxLength; length++) {
78 long startTime = System.currentTimeMillis();
79 FileChecker fileChecker = panel.getCurrentFileChecker();
80 int processorCount = Runtime.getRuntime().availableProcessors();
81 int numThreads = getThreadCount(charset.length(), length, processorCount);
82 logger.info("[{}]Current attempt length: {}, thread number: {}", fileChecker, length, numThreads);
83 password = startAndGet(numThreads, length, fileChecker, charset, panel);
84 long endTime = System.currentTimeMillis();
85 logger.info("Current attempt length: {}, Cost time: {}ms", length, endTime - startTime);
86 if (password != null || panel.getCurrentState() != State.WORKING) {
87 logger.info("Break state: {}", panel.getCurrentState());
88 break;
89 }
90 }
91 panel.showResultWithDialog(password);
92 }
93
94 @Override
95 public void cancel() {
96 if (bruteForceFuture != null) {
97 bruteForceFuture.cancel(false);
98 }
99 if (executorService != null && !executorService.isShutdown()) {
100 executorService.shutdown();
101 }
102 while (executorService != null && !executorService.isTerminated()) {
103 try {
104 final boolean isTimeout = !executorService.awaitTermination(100, TimeUnit.SECONDS);
105 logger.info("awaitTermination isTimeout: " + isTimeout);
106 } catch (InterruptedException e) {
107 logger.error("awaitTermination InterruptedException");
108 Thread.currentThread().interrupt();
109 }
110 }
111 }
112
113 private int getThreadCount(int charSetSize, int length, int maxThreadCount) {
114 int result = 1;
115 for (int i = 1; i <= length; i++) {
116 result *= charSetSize;
117 if (result >= maxThreadCount) {
118 return maxThreadCount;
119 }
120 }
121 return result;
122 }
123 }